﻿using System;
using System.Collections.Generic;
using PENet;
using UnityEngine;

/**
 * 技能管理器
 */

public class SkillMgr : MonoBehaviour{
    private ResSvc resSvc;
    private TimerSvc timerSvc;
    
    public void Init(){
        PECommon.Log("Init SkillMgr done");
        resSvc = ResSvc.Instance;
        timerSvc = TimerSvc.Instance;
    }

    public void SkillAttack(EntityBase entity, int skillId){
        AttackDamage(entity, skillId);
        AttackEffect(entity, skillId);
    }
    
    public void AttackDamage(EntityBase entity, int skillId){
        SkillCfg skillData = resSvc.GetSkillCfg(skillId);
        List<int> actionLst = skillData.skillActionLst;
        int sum = 0;
        for (int i = 0; i < actionLst.Count; i++){
            SkillActionCfg skillAction = resSvc.GetSkillActionCfg(actionLst[i]);
            sum += skillAction.delayTime;
            int index = i;
            if (sum > 0){
                timerSvc.AddTimerTask((int tid) => {
                    SkillAction(entity, skillData, index);
                }, sum);
            }
            else{
                //瞬时技能
                SkillAction(entity, skillData, index);
            }
        }
    }

    public void SkillAction(EntityBase entity, SkillCfg skillCfg, int index){
        SkillActionCfg skillActionCfg = resSvc.GetSkillActionCfg(skillCfg.skillActionLst[index]);

        int damage = skillCfg.skillDamageLst[index];
        
        //获取场景里怪物实体，遍历运算
        List<EntityBase> monsters = entity.battleMgr.GetEntityMonsters();
        for (int i = 0; i < monsters.Count; i++){
            EntityBase target = monsters[i];
            //判断距离，判断角度
            if (
                InRange(entity.GetPos(), target.GetPos(), skillActionCfg.radius) &&
                InAngle(entity.GetTransform(), target.GetPos(), skillActionCfg.angle)
            ){
                CalcDamage(entity,  target, skillCfg, damage);
            }
        }
    }

    private System.Random rd = new System.Random();
    private void CalcDamage(EntityBase entity, EntityBase target, SkillCfg skillCfg, int damage){
        int dmgSum = damage;
        if (skillCfg.dmgType == DamageType.AD){
            //计算闪避
            int dodgeNum = PETools.RDInt(1, 100, rd);
            if (dodgeNum <= target.Props.dodge){
                //UI显示闪避 TODO
                //PECommon.Log("闪避Rate:" + dodgeNum + "/" + target.Props.dodge);
                target.SetDodge();
                return;
            }
            //计算属性加成
            dmgSum += entity.Props.ad;

            //计算暴击
            int criticalNum = PETools.RDInt(1, 100, rd);
            if (criticalNum <= entity.Props.critical){
                float criticalRate = 1 + (PETools.RDInt(1, 100, rd)) / 100.0f;
                dmgSum = (int) criticalRate * dmgSum;
                //PECommon.Log("暴击Rate:" + criticalRate + "/" + entity.Props.critical);
                target.SetCritical(dmgSum);
            }

            //计算穿甲
            int addef = (int) ((1 - entity.Props.pierce / 100.0f) * target.Props.addef);
            dmgSum -= addef;
        }
        else if(skillCfg.dmgType == DamageType.AP){
            //计算属性加成
            dmgSum += entity.Props.ap;
    
            //计算魔法抗性
            dmgSum -= target.Props.apdef;
        }
        else{
            
        }
        //最终伤害
        if (dmgSum < 0){
            dmgSum = 0;
        }

        target.SetHurt(dmgSum);
        
        if (target.Hp < dmgSum){
            target.Hp = 0;
            //目标死亡
            target.Die();
            target.battleMgr.RemoveMonster(target.Name);
        }
        else{
            target.Hp -= dmgSum;
            target.Hit();
        }
    }
    
    private bool InRange(Vector3 from, Vector3 to, float range){
        float dis = Vector3.Distance(from, to);
        return dis <= range;
    }

    private bool InAngle(Transform trans, Vector3 to, float angle){
        return true;
    }

    /**
     * 技能效果表现
     */
    public void AttackEffect(EntityBase entity, int skillId){
        SkillCfg skillData = resSvc.GetSkillCfg(skillId);
        //PECommon.Log("" + skillData.aniAction);
        entity.SetAction(skillData.aniAction);
        entity.SetFx(skillData.fx, skillData.skillTime);
        
        CalcSkillMove(entity, skillData);

        timerSvc.AddTimerTask((int tid) => {
            entity.Idle();
        }, skillData.skillTime);
    }

    private void CalcSkillMove(EntityBase entity, SkillCfg skillData){
        List<int> moveLst = skillData.skillMoveLst;
        int sum = 0;
        for (int i = 0; i < moveLst.Count; i++){
            SkillMoveCfg skillMoveCfg = resSvc.GetSkillMoveCfg(moveLst[i]);
            float speed = skillMoveCfg.moveDis / (skillMoveCfg.moveTime / 1000f);
            sum += skillMoveCfg.delayTime;
            if (sum > 0){
                timerSvc.AddTimerTask((int tid) => {
                    entity.SetSkillMoveState(true, speed);
                }, sum);
            }
            else{
                entity.SetSkillMoveState(true, speed);
            }

            sum += skillMoveCfg.moveTime;
            timerSvc.AddTimerTask((int tid) => {
                entity.SetSkillMoveState(false);
            }, sum);
        }
    }
}
